<?php
namespace Matrix;

/**
 * 复数类
 *
 * 主要用来转换英语单词的单复数形式
 *
 * 将复数单词转换为单数:
 * <code>
 * $plu = new Pluralizer;
 * $plu->singular('directories');
 * </code>
 * 
 * 将单数转换为复数:
 * <code>
 * $plu->plural('directory');
 * </code>
 */
class Pluralizer
{
	/**
	 * 配置数组, 来自于./application/config/strings.php
	 *
	 * @var array
	 */
	protected $config = array();
	
	/**
	 * 复数词的缓存
	 *
	 * @var array
	 */
	protected $plural = array();
	
	/**
	 * 单数词的缓存
	 *
	 * @var array
	 */
	protected $singular = array();
	
	/**
	 * 创建一个新的实例
	 *
	 * @param	array	$config
	 * @return	void
	 */
	public function __construct($config)
	{
		$this->config = $config;
	}
	
	/**
	 * 获取指定词的单数词
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public function singular($value)
	{
		if (isset($this->singular[$value])) {
			return $this->singular[$value];
		}
		$irregular = $this->config['irregular'];
		$result = $this->auto($value, $this->config['singular'], $irregular);
		return $this->singular[$value] = $result ? $result : $value;
	}
	
	/**
	 * 获取指定词的复数词
	 *
	 * @param	string	$value
	 * @param	integer	$count
	 * @return	string
	 */
	public function plural($value, $count = 2)
	{
		if (intval($count) === 1) {
			return $value;
		}
		if (isset($this->plural[$value])) {
			return $this->plural[$value];
		}
		$irregular = array_flip($this->config['irregular']);
		$result = $this->auto($value, $this->config['plural'], $irregular);
		return $this->plural[$value] = $result ? $result : $value;
	}
	
	/**
	 * 转换一个英语单词
	 *
	 * @param	string	$value
	 * @param	array	$source
	 * @param	array	$irregular
	 * @return	mixed
	 */
	protected function auto($value, $source, $irregular)
	{
		if (in_array(Str::lower($value), $this->config['uncountable'])) {
			return $value;
		}
		foreach ($irregular as $irregular => $pattern) {
			if (preg_match($pattern = '/'.$pattern.'$/i', $value)) {
				return preg_replace($pattern, $irregular, $value);
			}
		}
		foreach ($source as $pattern => $inflected) {
			if (preg_match($pattern, $value)) {
				return preg_replace($pattern, $inflected, $value);
			}
		}
	}
}